<?php
class CV_Filter_Input extends Zend_Filter_Input{
	const TRAVERSE_ARRAY = 'traverseArray';
	public function __construct($filterRules, $validatorRules, array $data = null, array $options = null){
		$this->_defaults[self::TRAVERSE_ARRAY] = true;
		parent::__construct($filterRules, $validatorRules, $data, $options);
	}

	public function setOptions(array $options){
		foreach ($options as $option => $value) {
			switch ($option) {
				case self::TRAVERSE_ARRAY:
					$this->_defaults[$option] = $value;
					unset($options[$option]);
					break;
			}
		}
		parent::setOptions( $options );
	}

	/**
	 * no array recursion
	 */
	protected function _filterRule(array $filterRule)
	{
		$field = $filterRule[self::FIELDS];
		if (!array_key_exists($field, $this->_data)) {
			return;
		}
		if ($this->_defaults[self::TRAVERSE_ARRAY] && is_array($this->_data[$field])) {
			foreach ($this->_data[$field] as $key => $value) {
				$this->_data[$field][$key] = $filterRule[self::FILTER_CHAIN]->filter($value);
			}
		} else {
			 $this->_data[$field] =
				$filterRule[self::FILTER_CHAIN]->filter($this->_data[$field]);
		}
	}
	/**
	 * @param array $validatorRule
	 * @return void
	 */
	protected function _validateRule(array $validatorRule)
	{
			/**
			 * Get one or more data values from input, and check for missing fields.
			 * Apply defaults if fields are missing.
			 */
			$data = array();
			foreach ((array) $validatorRule[self::FIELDS] as $field) {
					if (array_key_exists($field, $this->_data)) {
							$data[$field] = $this->_data[$field];
					} else
					if (array_key_exists(self::DEFAULT_VALUE, $validatorRule)) {
							if (is_array($validatorRule[self::DEFAULT_VALUE])) {
									$key = array_search($field, (array) $validatorRule[self::FIELDS]);
									if (array_key_exists($key, $validatorRule[self::DEFAULT_VALUE])) {
											$data[$field] = $validatorRule[self::DEFAULT_VALUE][$key];
									}
							} else {
									$data[$field] = $validatorRule[self::DEFAULT_VALUE];
							}
					} else
					if ($validatorRule[self::PRESENCE] == self::PRESENCE_REQUIRED) {
							$this->_missingFields[$validatorRule[self::RULE]][] =
									$this->_getMissingMessage($validatorRule[self::RULE], $field);
					}
			}

			/**
			 * If any required fields are missing, break the loop.
			 */
			if (isset($this->_missingFields[$validatorRule[self::RULE]]) && count($this->_missingFields[$validatorRule[self::RULE]]) > 0) {
					return;
			}

			/**
			 * Evaluate the inputs against the validator chain.
			 */
			if (count((array) $validatorRule[self::FIELDS]) > 1) {
					if (!$validatorRule[self::VALIDATOR_CHAIN]->isValid($data)) {
							$this->_invalidMessages[$validatorRule[self::RULE]] = $validatorRule[self::VALIDATOR_CHAIN]->getMessages();
							$this->_invalidErrors[$validatorRule[self::RULE]] = $validatorRule[self::VALIDATOR_CHAIN]->getErrors();
							return;
					}
			} else {
					$failed = false;
					foreach ($data as $fieldKey => $field) {
							if (!$this->_defaults[self::TRAVERSE_ARRAY] || !is_array($field)) {
									$field = array($field);
							}
							foreach ($field as $value) {
									if (empty($value)) {
											if ($validatorRule[self::ALLOW_EMPTY] == true) {
													continue;
											}
											if ($validatorRule[self::VALIDATOR_CHAIN_COUNT] == 0) {
													$notEmptyValidator = $this->_getValidator('NotEmpty');
													$notEmptyValidator->setMessage($this->_getNotEmptyMessage($validatorRule[self::RULE], $fieldKey));
													$validatorRule[self::VALIDATOR_CHAIN]->addValidator($notEmptyValidator);
											}
									}
									if (!$validatorRule[self::VALIDATOR_CHAIN]->isValid($value)) {
											$this->_invalidMessages[$validatorRule[self::RULE]] =
													$validatorRule[self::VALIDATOR_CHAIN]->getMessages();
											$this->_invalidErrors[$validatorRule[self::RULE]] =
													$validatorRule[self::VALIDATOR_CHAIN]->getErrors();
											unset($this->_validFields[$fieldKey]);
											$failed = true;
											if ($validatorRule[self::BREAK_CHAIN]) {
													return;
											}
									}
							}
					}
					if ($failed) {
							return;
					}
			}

			/**
			 * If we got this far, the inputs for this rule pass validation.
			 */
			foreach ((array) $validatorRule[self::FIELDS] as $field) {
					if (array_key_exists($field, $data)) {
							$this->_validFields[$field] = $data[$field];
					}
			}
	}
}